#pragma once
#include <assert.h>
#include <vector>

#include "Utility/Logging/SGLogger.h"
#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Common/Constant.h"
#include "DataStructure/Common/Out.h"
#include "DataStructure/Common/Real.h"
#include "DataStructure/Common/SGNamespace.h"

#include "BeamSecElementTypes.h"

SG_NAMESPACE_OPEN
namespace FEMSolver
{
    namespace Element
    {
        struct Point2D
        {
            int    nodeId;
            SG::DataStructure::Common::Real y;
            SG::DataStructure::Common::Real z;
        };
        using NodeSet = std::vector<Point2D>;

        struct Element
        {
            int              eleId;
            std::vector<int> nodes;                 // 注意，Element存储节点ID
        };
        using ElementSet = std::vector<Element>;

        struct Meshes
        {
            NodeSet    nodes;
            ElementSet q9Elements;
            ElementSet t6Elements;

            /**
             * @brief 清空数据
             *
             * 该函数用于清空对象的所有数据成员。
             * 包括各种容器和对象，以确保在下一次使用时它们处于初始状态。
             */
            void clear ()
            {
                nodes.clear ();
                q9Elements.clear ();
                t6Elements.clear ();
            }

            const ElementSet& GetElement (SG::FEMSolver::BeamElement::BeamSecElementTypes type) const
            {
                switch (type)
                {
                    case 0:  // 对应 Q9 单元类型
                        return q9Elements;
                    case 1:  // 对应 T6 单元类型
                        return t6Elements;
                    // 新增加单元时需追加 case
                    
                    default:
                        SGFatal << "The element type is not support: "<< type ;
                        static ElementSet emptyElementSet;
                        return emptyElementSet;
                }
            }

            // 辅助方法：获取网格中存在的单元类型
            std::vector<SG::FEMSolver::BeamElement::BeamSecElementTypes> GetAllElementTypes() const;

            // 辅助方法：获取单元节点坐标矩阵
            SG::Algebra::Matrixd ExtractElementNodeCoords (const std::vector<int>& nodeIds) const;

            // 辅助方法：平移网格中所有节点坐标、
            void TranslateNodes (const SG::DataStructure::Common::Real yS, const SG::DataStructure::Common::Real zS);
        };
           
        /// @brief 重载 ==，判断两个 Point2D 在容差 TOLERANCE 范围内是否相等
        inline bool operator== (const Point2D& p1, const Point2D& p2)
        {
            if (p1.nodeId != p2.nodeId)
                return false;
            if (fabs (p1.y - p2.y) > SG::DataStructure::Common::TOLERANCE || fabs (p1.z - p2.z) > SG::DataStructure::Common::TOLERANCE)
                return false;
            return true;
        }

        /// @brief 重载 ==，判断两个 Element 在容差 TOLERANCE 范围内是否相等
        inline bool operator== (const Element& ele1, const Element& ele2)
        {
            if (ele1.eleId != ele2.eleId || ele1.nodes != ele2.nodes)
                return false;
            return true;
        }

        /// @brief 重载 ==，判断两个 Meshes 在容差 TOLERANCE 范围内是否相等
        inline bool operator== (const Meshes& meshes1, const Meshes& meshes2)
        {
            if (meshes1.nodes != meshes2.nodes || meshes1.q9Elements != meshes2.q9Elements || meshes1.t6Elements != meshes2.t6Elements)
                return false;
            return true;
        }
        
    };
};
SG_NAMESPACE_CLOSE